<template>
  <el-card class="menu_manage">
    <template #header>
      <div class="menu_manage_handle">
        <p>菜单管理</p>
        <el-button
          type="primary"
          size="small"
          plain
          @click="handleSave()"
        >
          新增
        </el-button>
      </div>
    </template>
    <ev-table
      :data="menuList"
      :table-config="tableConfig"
      row-key="id"
      :default-sort="{ prop: 'orderNum', order: 'descending' }"
    >       
      <template #appType="scope"> 
        <div>
          {{ dictFormat(scope.row.appType) }}
        </div>
      </template>
      <template #opt="{row}">
        <el-link
          type="primary"
          size="small"
          @click="handleUpdate(row)"
        >
          编辑
        </el-link>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        <el-popconfirm
          title="确定要删除吗?"
          confirm-button-text="确定"
          cancel-button-text="取消"
          @confirm="handleDelete(row)"
        >
          <template #reference>
            <el-link
              type="danger"
              size="small"
            >
              删除
            </el-link>
          </template>
        </el-popconfirm>
      </template>
    </ev-table>
    <el-dialog
      v-model="showDialog"
      width="30%"
      :lock-scroll="false"
      draggable
      align-center
      center
    >
      <template #header>
        <p>{{ chooseHandle == 'update' ? '编辑菜单' : chooseHandle == 'save' ? '新增菜单' : '' }}</p>
      </template>
      <el-form
        :model="menuForm"
        label-position="right"
        label-width="100px"
      >
        <el-form-item
          v-show="chooseHandle != 'save'"
          label="菜单id"
        >
          <el-input
            v-model="menuForm.appId"
            placeholder="请输入菜单id"
            clearable
            :disabled="chooseHandle == 'update'"
            style="width:300px"
          />
        </el-form-item>
        <el-form-item label="上级分类">
          <el-tree-select
            v-model="menuForm.pid"
            :data="tree"
            check-strictly
            node-key="appId"
            style="width:300px"
            :props="{
              label:'appName',
              disabled: 'disabled',
            }"
          > 
          </el-tree-select>
        </el-form-item>
        <el-form-item label="菜单名称">
          <el-input
            v-model="menuForm.appName"
            placeholder="请输入菜单名称"
            clearable
            style="width:300px"
          />
        </el-form-item>
        <el-form-item label="菜单类型">
          <el-select 
            v-model="menuForm.appType" 
            placeholder="请选择菜单类型"
            style="width:300px"
            :disabled="chooseHandle == 'update'"
          >
            <el-option
              v-for="item in dictData"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="排序号">
          <el-input-number
            v-model="menuForm.orderNum"
            style="width:300px"
          />
        </el-form-item>
        <el-form-item label="描述">
          <el-input
            v-model="menuForm.description"
            :rows="2"
            type="textarea"
            placeholder="请输入描述"
            clearable
            style="width:300px"
          />
        </el-form-item>
        <el-form-item label="图标">
          <el-select 
            v-model="menuForm.icon" 
            placeholder="请选择菜单图标"
            clearable
            filterable
            style="width:300px"
            no-data-text="无数据"
            center
          >
            <el-option
              v-for="item in iconfontData"
              :key="item['icon_id']"
              :label="item['name']"
              :value="item['font_class']"
            >
              <i 
                class="iconfont" 
                :class="`icon-${item['font_class']}`"
              ></i>&nbsp;&nbsp;&nbsp;<span>{{ item['font_class'] }}</span>
            </el-option>
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="showDialog = false;resetForm();">取消</el-button>
          <el-button
            type="primary"
            @click="handleMenu"
          >
            确定
          </el-button>
        </span>
      </template>
    </el-dialog>
  </el-card>
</template>

<script setup lang="ts" name="menuManage">
import { ref, onMounted, reactive } from 'vue'
import api from './service/api'
import { ElMessage } from 'element-plus'
import tableConfig from './config/index'
import commonApi from '@/api/common/index'
import iconfontJson from '@/assets/iconfont/iconfont.json'

interface dict {
  value:string,
  label:string
}

const menuForm = reactive({
    appId: '',
    appName: '',
    appType: '',
    orderNum: 1,
    pid: '',
    description: '',
    icon: '',
})
const dictData = ref<dict[]>([])
const menuList = ref([])
const showDialog = ref(false)
const chooseHandle = ref('')
const tree = reactive([])
const iconfontData = ref([])

//  重置表单
const resetForm = () => {
    Object.assign(menuForm, {
        appId: '',
        appName: '',
        appType: '',
        orderNum: 1,
        pid: '',
        description: '',
        icon: '',
    })
    chooseHandle.value = ''
}

const handleSave = () => {
    resetForm()
    chooseHandle.value = 'save'
    deepTree(tree, { }, 'unDisableChildren')
    showDialog.value = true
}

const deepTree = (data:any, obj:object, type:string) => {
    data.forEach(ele => {
        if (obj.appId && (ele.appId == obj.appId || type == 'disableChildren')) {
            ele.disabled = true
            if (ele.children) {
                deepTree(ele.children, obj, 'disableChildren')
            }
        } else {
            ele.disabled = false
            if (ele.children) {
                deepTree(ele.children, obj, 'unDisableChildren')
            }
        } 
    })
}

const handleUpdate = (obj:any) => {
    chooseHandle.value = 'update'
    deepTree(tree, obj, 'unDisableChildren')
    Object.assign(menuForm, obj)
    Reflect.has(menuForm, 'id') ? delete menuForm.id : ''
    showDialog.value = true
}

const handleDelete = (data:object) => {
    Object.assign(menuForm, data)
    Reflect.has(menuForm, 'id') ? delete menuForm.id : ''
    deleteMenuList(menuForm)
    resetForm()
}

const getMenuList = () => {
    api.getMenuList().then((res:any) => {
        if (res.code === 0) {
            menuList.value = res.data
        } else {
            ElMessage({
                message: res.msg,
                type: 'warning',
            })
        }
    }) 
} 

const dictFormat = (appType:string) => {
    let cur = dictData.value.find(e => e.value == appType)
    if (cur) {
        return cur.label
    }
    return '-'
}

const deleteMenuList = (data:object) => {
    api.deleteMenuList(data).then((res:any) => {
        if (res.code === 0) {
            ElMessage({
                message: res.msg,
                type: 'success',
            })
            getMenuList()
            getTree()
        } else {
            ElMessage({
                message: res.msg,
                type: 'warning',
            })
        }
    })
}

const updateMenuList = (data:object) => {
    api.updateMenuList(data).then((res:any) => {
        if (res.code === 0) {
            ElMessage({
                message: res.msg,
                type: 'success',
            })
            getMenuList()
            getTree()
        } else {
            ElMessage({
                message: res.msg,
                type: 'warning',
            })
        }
    })
}

const saveMenuList = (data:object) => {
    api.saveMenuList(data).then((res:any) => {
        if (res.code === 0) {
            ElMessage({
                message: res.msg,
                type: 'success',
            })
            getMenuList()
            getTree()
        } else {
            ElMessage({
                message: res.msg,
                type: 'warning',
            })
        }
    })
}

const handleMenu = () => {
    switch (chooseHandle.value) {
        case 'save':
            saveMenuList(menuForm)
            resetForm()
            break
        case 'update':
            updateMenuList(menuForm)
            resetForm()
            break
    }
    showDialog.value = false
}

const getTree = () => {
    api.getTree()
    .then(res => {
        const { code, data, msg } = res
        if (code == 0) {
            Object.assign(tree, data)
        } else {
            ElMessage.error(msg)
        }
    })
}

const getDictData = () => {
    commonApi.getDict('menu').then(res => {
        const { code, data, msg } = res
        if (code == 0) {
            dictData.value = data
        } else {
            ElMessage({
                message: res.msg,
                type: 'warning',
            })
        }
    })
}

onMounted(() => {
    iconfontData.value = iconfontJson.glyphs
    getDictData()
    getMenuList()
    getTree()
})
</script>

<style scoped lang="scss">
.menu_manage{
  .menu_manage_handle{
    display: flex;
    align-items: center;
    justify-content: space-between;
  }
}
.iconfont{
    font-size: 16px;
}
</style>